#include "slidepaintbox.h"
#include "lp_types.h"
#include "slidegenerator.h"
#include <QtXml>
#include <iostream>

void SlidePaintBox::PaintLinePlan(TupleItr dynEm, SlideModel& model, std::vector<StopData>& stopList, StopItr& currentStopItr){

    TupleItr rootItr = model.GetRootTuple();
    QDomElement dynElement = dynEm->self.toElement();

    QDomDocument doc("LinePlan");


    struct {int x1, y1, x2, y2, range, index;} lpData;

    lpData.x1 = dynElement.attribute("x1","256").toInt(0,10);
    lpData.x2 = dynElement.attribute("x2","712").toInt(0,10);
    lpData.y1 = dynElement.attribute("y1","400").toInt(0,10);
    lpData.y2 = dynElement.attribute("y2","400").toInt(0,10);
    lpData.range = dynElement.attribute("range","0").toInt(0,10);
    lpData.index = dynElement.attribute("index","0").toInt(0,10);

    int stopCount = stopList.size();
    StopItr startItr, endItr;
    startItr = stopList.begin();
    endItr = --stopList.end();

    //Set the start point of the displayed stops, relative to the current stop
    //Halt if we hit the bounds of the list
    if (lpData.range > 1 && lpData.range < stopCount){
        if (lpData.range > (signed)stopList.size()) lpData.range = stopList.size();

        stopCount = lpData.range;
        startItr = currentStopItr;

        if (lpData.index >= 0){
            for (int i = 0; i < lpData.index; i++){
                if (startItr == --stopList.end()) break;
                startItr++;
            }
        } else {
            for (int i = 0; i > lpData.index; i--){
                if (startItr == stopList.begin()) break;
                startItr--;
            }
        }

        endItr = startItr;
        for (int j = 1; j < lpData.range; j++){
            if (endItr == --stopList.end()) break;
            endItr++;
        }

        if (((signed)stopList.size() - currentStopItr->order) < lpData.range + lpData.index){

            startItr = stopList.end() - (lpData.range);

        }

    }

    int lineLength = (lpData.x2 - lpData.x1);
    int stopIncrement = lineLength / (stopCount - 1);
    int x = 0;

    for (; startItr->order <= endItr->order && startItr != stopList.end(); startItr++){
        //std::cout << "Current: " << startItr->order << " End: " << endItr->order << "\n";

        QDomElement lineEm = doc.createElement("line");
        QDomElement stopCircleEm = doc.createElement("circle");
        QDomElement stopTextEm = doc.createElement("text");
        QDomElement correspTextEm = doc.createElement("text");

        QDomText text = doc.createTextNode(startItr->stopName);
        QDomText ctext = doc.createTextNode(startItr->correspondances);


        lineEm.setAttribute("y1",lpData.y1);
        lineEm.setAttribute("y2",lpData.y1);
        lineEm.setAttribute("x1",lpData.x1 + x);
        lineEm.setAttribute("x2",lpData.x1 + x + stopIncrement);

        stopCircleEm.setAttribute("cx",lpData.x1 + x);
        stopCircleEm.setAttribute("cy",lpData.y1);
        stopCircleEm.setAttribute("r",10);

        stopTextEm.setAttribute("x",lpData.x1 + x + 14);
        stopTextEm.setAttribute("y",lpData.y1 - 15);

        //TODO: Handle Text Transformation Attributes properly
        char transformCoords[24];
        sprintf(transformCoords, "rotate(-60 %d %d)", lpData.x1 + x + 14, lpData.y1 - 15);
        stopTextEm.setAttribute("transform", transformCoords);

        correspTextEm.setAttribute("x",lpData.x1 + x + 30);
        correspTextEm.setAttribute("y",lpData.y1 - 15);
        sprintf(transformCoords, "rotate(-60 %d %d)", lpData.x1 + x + 30, lpData.y1 - 15);
        correspTextEm.setAttribute("transform", transformCoords);

        x += stopIncrement;


        //Set Styling Information

        correspTextEm.setAttribute("class", "correspondance");        
        TupleItr correspTextItr = model.AddTuple(Tuple(rootItr, correspTextEm));

        if (startItr == currentStopItr){
            lineEm.setAttribute("class", (startItr->nextLineIsSecondary)
            ? "secondary" : "primary");
            stopCircleEm.setAttribute("class", "next_stop_icon");
            stopTextEm.setAttribute("class","next_stop");

        } else if (startItr->order < currentStopItr->order){
            lineEm.setAttribute("class", (startItr->nextLineIsSecondary)
            ? "secondary_traversed" : "primary_traversed");
            stopCircleEm.setAttribute("class", "previous_stop_icon");
            stopTextEm.setAttribute("class","previous_stop");
        } else {
            lineEm.setAttribute("class", (startItr->nextLineIsSecondary)
            ? "secondary" : "primary");
            stopCircleEm.setAttribute("class", "stop_icon");
            stopTextEm.setAttribute("class","stop");
        }

        text.setNodeValue(startItr->stopName);
        ctext.setNodeValue(startItr->correspondances);
        model.AddTuple(Tuple(correspTextItr, ctext));
        TupleItr stopTextItr = model.AddTuple(Tuple(rootItr, stopTextEm));

        if (startItr == stopList.begin()){

            stopCircleEm.setAttribute("class", "terminal_stop_icon");

        } else if (startItr->order == stopList.back().order) {

            stopCircleEm.setAttribute("class", "terminal_stop_icon");            

        } else model.AddTuple(Tuple(stopTextItr, text));

        if (startItr->order < endItr->order) model.AddTuple(Tuple(rootItr, lineEm));

        model.AddTuple(Tuple(rootItr, stopCircleEm));
    }


}

void SlidePaintBox::PaintMultiText(TupleItr dynEm, SlideModel& model, std::vector<StopData>& stopList, StopItr& stop, std::string routeID){


    TupleItr root = model.GetRootTuple();
    TupleItr textItr;
    QDomElement dynamicElement = dynEm->self.toElement();
    QDomDocument doc("LinePlan");
    QString string;

    {
        std::string id = dynamicElement.attribute("id","").toStdString();
        if (id == "@first")
            string = stopList.front().stopName;

        else if (id == "@last")
            string = stopList.back().stopName;

        else if (id.find("@rel=",0,5) != std::string::npos){
         int index = atoi(id.substr(5, (id.size() - 5 )).c_str()) + stop->order;

         //Prevent Over/Underrun
         if (index > (signed)stopList.size())
             string = stopList.back().stopName;
         else if (index < 1)
             string = stopList.front().stopName;
         else string = stopList.at(index - 1).stopName;

        }

        else if (id.find("@abs=",0,5) != std::string::npos){
            int index = atoi(id.substr(5, (id.size() - 5 )).c_str()) - 1;
            if (index >= 0 && index < (signed)stopList.size())
                string = stopList.at(index).stopName;
        }

        else if (id == "@routeNum")
            string = QString::fromStdString(routeID);
        else string = "";
    }

    QStringList wordQueue = string.split(QRegExp("[-\\s]"));

    //TODO: Accurately find the pixel width of a rasterised line of text
    const float fontWidthRatio = 1.8; //9:5 ~= Avg ratio of font height to width
    int fontSize = dynamicElement.attribute("font-size","20").toInt(0,10);
    int fontWidth = fontSize / fontWidthRatio;

    QString currentString;
    int currentStringLength = 0;
    int lineCount = 0;    

    while (!wordQueue.isEmpty()){

        currentString.clear();
        currentStringLength = 0;

        //Always add at least one string to the line
        currentString.append(wordQueue.front());
        currentStringLength += (wordQueue.front().size() + 1);
        wordQueue.pop_front();

        while (!wordQueue.isEmpty()){
            currentStringLength += (wordQueue.front().size() + 1);
            //Only add word if it won't exceed the max length of the field
            if ((currentStringLength * fontWidth) < dynamicElement.attribute("width","1").toInt(0,10)){
                currentString.append(QString::fromAscii(" ") + wordQueue.front());
                wordQueue.pop_front();
            } else break; //Otherwise leave it for the next line
        }

        //Append the line to the root tuple as a text element
        QDomElement textEm = doc.createElement("text");
        QDomText txt = doc.createTextNode(currentString);
        textEm.setAttribute("font-size",fontSize);
        textEm.setAttribute("class", dynamicElement.attribute("class",""));
        textEm.setAttribute("x", dynamicElement.attribute("x","0").toInt(0,10));
        textEm.setAttribute("y", dynamicElement.attribute("y","0").toInt(0,10) + (lineCount * fontSize));


        textItr = model.AddTuple(Tuple(root, textEm));
        model.AddTuple(Tuple(textItr, txt));

        lineCount++;
    }

}

void SlidePaintBox::PaintGraphicsFrame(TupleItr dynEm, SlideModel& model, std::vector<StopData>& stopList, StopItr& stop){

}
